﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using BarStructures.Deformed;
using System.Drawing.Drawing2D;

namespace BarStructures
{
    public class Bar: IEquatable<Bar>
    {
        public BarPhysicalProperties Phys { get; set; }

        public Node NodeOne { get; private set; }

        public Node NodeTwo { get; private set; }

        internal Bar(Node nodeOne, Node nodeTwo, BarPhysicalProperties phys)
        {
            this.Phys = phys;
            this.NodeOne = nodeOne;
            this.NodeTwo = nodeTwo;
        }

        public double Length
        {
            get
            {
                double x = NodeOne.X - NodeTwo.X;
                double y = NodeOne.Y - NodeTwo.Y;
                return Math.Sqrt(x * x + y * y);
            } 
        }
        
        public double Cos
        {
            get { return (NodeTwo.X - NodeOne.X) / Length; }
        }

        public double Sin
        {
            get { return (NodeTwo.Y - NodeOne.Y) / Length; }
        }

        #region IEquatable<Bar> Members

        public bool Equals(Bar other)
        {
            return this.NodeOne.Equals(other.NodeOne) && this.NodeTwo.Equals(other.NodeTwo);
        }

        #endregion

        public void Draw(IDrawBoard d)
        {
            PointF a = d.GetWindowCoordinates(NodeOne.X, NodeOne.Y);
            PointF b = d.GetWindowCoordinates(NodeTwo.X, NodeTwo.Y);
            Graphics g = d.GetGraphics();
            g.DrawLine(Pens.Blue, a, b);
        }

        public void Draw(IDrawBoard d, NodeDisplacement da, NodeDisplacement db, bool frameCurve, double scale)
        {
            Graphics g = d.GetGraphics();

            Pen pen = new Pen(Brushes.Red);
            pen.DashStyle = DashStyle.Dot;

            if (frameCurve)
            {
                PointF[] pfa = new PointF[7];

                for (int i = 0; i < pfa.Length; i++)
                {
                    PointF p = this.GetYDisplacementCoordinate((float)(i * this.Length / 6), da, db, scale);
                    PointF pgl = new PointF((float)(this.NodeOne.X + p.X * this.Cos - p.Y * this.Sin), (float)(this.NodeOne.Y + p.X * this.Sin + p.Y * this.Cos));
                    pfa[i] = d.GetWindowCoordinates(pgl.X, pgl.Y);
                }
                g.DrawCurve(pen, pfa);
            }
            else
            {
                PointF a = d.GetWindowCoordinates(NodeOne.X + da.Dx * scale, NodeOne.Y + da.Dy * scale);
                PointF b = d.GetWindowCoordinates(NodeTwo.X + db.Dx * scale, NodeTwo.Y + db.Dy * scale);
                g.DrawLine(pen, a, b);
            }
        }

        private PointF GetYDisplacementCoordinate(float x, NodeDisplacement da, NodeDisplacement db, double scale)
        {
            float x2 = x * x;
            float x3 = x2 * x;

            float l = (float)this.Length;
            float l2 = l * l;
            float l3 = l2 * l;

            //Локальные перемещения узлов
            float dy1l = (float)(da.Dy * scale * this.Cos - da.Dx * scale * this.Sin);
            float dx1l = (float)(da.Dx * scale * this.Cos + da.Dy * scale * this.Sin);
            float dy2l = (float)(db.Dy * scale * this.Cos - db.Dx * scale * this.Sin);
            float dx2l = (float)(db.Dx * scale * this.Cos + db.Dy * scale * this.Sin);

            //в локальной системе координат
            float y = (float)(dy1l * (1 - 3 * x2 / l2 + 2 * x3 / l3) + dy2l * (3 * x2 / l2 - 2 * x3 / l3) +
                da.Da * (x - 2 * x2 / l + x3 / l2) + db.Da * (-x2 / l + x3 / l2));

            return new PointF((float)(dx1l + x * (1 + (dx2l - dx1l) / Length)), y);
        }


    }
}
